//
//  IMTCANMessage.h
//  ROCOMO
//
//  Created by Kyle Sun on 7/25/16.
//  Copyright © 2016 ROCOMO. All rights reserved.
//

#import <Foundation/Foundation.h>

#define CANFormatStandard 0x00 // 标准格式
#define CANFormatExtended 0x01 // 扩展格式
#define CANTypeData       0x00 // 数据帧
#define CANTypeRemote     0x01 // 远程帧
#define CANFrameHead      0xAA
#define CANFrameTail      0x55
#define CANFrameControl   0xA5

// 新协议
#define NEWFORMHEADER          0xAA // 协议头
#define NEWESCAPECHARACTER     0xA5 // 转义字符
#define IMCHECKTYPE              1  // 校验方式


/* CAN消息结构体
 * __attribute__((packed))的作用是使变量使用最小的字节对齐方式，即一字节对齐
 */
typedef struct {
    u_int32_t cid;
    u_int64_t data;
    u_int8_t length;
    u_int8_t channel;
    u_int8_t format;
    u_int8_t type;
} __attribute__((packed)) IMTCANMessageBody;

typedef struct {
    int32_t param0;
    int32_t param1;
} __attribute__((packed)) IMTS32Params;

typedef struct {
    u_int32_t param1;
    u_int32_t param2;
} __attribute__((packed)) IMTU32Params;

typedef struct {
    int8_t force;        //助力强度      √
    int8_t sensitivity;  //助力启动灵敏度     StartAgility
    int8_t lastTime;     // 助力启动强度      StopAgility
    int8_t startupSpeed; //助力启动速度       StartEnergyModel   √     (单位：0.1km/h)
    int8_t division;     // 油门启动强度          √
    int8_t reserve1;     //最大功率百分比限制       √
    int8_t mode;         // 判断模式: 0:节能，1：正常，2：极速，3：学习者
    int8_t maxSpeed;     // 限速设定         （单位：0.25km/h）
} __attribute__((packed)) IMTP2S32Params;

//遥控格式
typedef struct {
    u_int16_t isOn;
    int16_t offset;
    int32_t speed;
} __attribute__((packed)) IMTControlParams;

typedef struct {
    u_int16_t param0;
    u_int16_t param1;
    u_int32_t param2;
} __attribute__((packed)) IMTComboParams;

// 确认信息
typedef struct {
    UInt8 connection: 1;
    UInt8 communicationMode: 1;
    UInt8 frequency: 6;
    UInt8 reserved[7];
} __attribute__((packed)) IMTComfirmParams;

// 车辆广播数据
typedef struct {
    UInt16 model;
    UInt8 characteristic:5;
    UInt8 content:3;
    UInt8 password[6];
    UInt64 sn;
    UInt8 batteryPercentage;
} __attribute__((packed)) IMTCarAdvertisementParams;

extern const u_int8_t kIMTCANMessageExtendedDataLength1;
extern const u_int8_t kIMTCANMessageStandardDataLength1;
extern const u_int8_t kIMTCANMessageDefaultChannel;
extern const u_int8_t kIMTCANMessageStandardFrameLength;

// 新协议
/*
 * format结构
 * @parame ：(uint8_t)formatType，bit【7】帧格式类型，0:默认值，1:拓展帧格式，format向后扩展最高字节表示是否继续扩展。
 * @parame ：(uint8_t)isHasTab， bit[6] 是否包含tab【0-4】字节
 * @parame ：(uint8_t)checkType， bit[5-4] 校验方式，0:无校验，1:奇偶校验，2:CRC16,3:CRC32
 * @parame ：(uint8_t)isEncrypt， bit[3] 是否加密
 * @parame ：(uint8_t)dataType， bit[2-0] 数据，1、2、3:标准组，4、5、6:专用组
 */
typedef struct {
    uint8_t formatType;
    uint8_t isHasTab;
    uint8_t checkType;
    uint8_t isEncrypt;
    uint8_t dataType;
}__attribute__((packed)) IM_NewMessageFormat;

/*
 * data结构 - 标准组
 * @parame ：(uint8_t)source， 来源设备 - 数据帧方向
 * @parame ：(uint8_t)target， 目标设备 - 读写属性
 * @parame ：(uint8_t)channel， 通道 - 数据帧方向 ，最高字节表示数据帧方向，主机发向从机最高位置0，从机应答主机最高位置1
 * @parame ：(uint8_t)property， 属性 - 最高位表示读写属性，0表示读，1表示写
 * @parame ：(NSData *)para， 参数数据
 */
typedef struct {
    uint8_t source;
    uint8_t target;
    uint8_t channel;
    uint8_t property;
}__attribute__((packed)) IM_NewStandardDataFormat;

/*
 * data结构 - 专用组
 * @parame ：(uint8_t)source， 来源设备 - 数据帧方向
 * @parame ：(uint8_t)target， 目标设备 - 读写属性
 * @parame ：(uint32_t)cmd， 功能号 byte[1-4]，大端模式cmd 第一个字节的最高位 bit7 表示数据帧方向，主机发向从机最高位置 0，从机 应答主机最高位置 1(从机将收到的通道最高位置 1 回复给主机即可)次高位      bit6 用于表示读写属性，0 表示读，1 表示写bit5 用于表示 cmd 位数扩展，bit5 为 1 表示 Cmd 扩展一个字节，最多扩展 3 个 字节
 * @parame ：(NSData *)para， 参数数据
 */
typedef struct {
    uint8_t source;
    uint8_t target;
    uint32_t cmd;
}__attribute__((packed)) IM_NewDedicatedDataFormat;

/*
 * 协议数据结构
 * @parame ：(IM_NewMessageFormat)format，
 * @parame ：(uint8_t)key，密钥索引，是否存在由 Format 指定，如使用密钥则其后全为密文
 * @parame ：(uint32_t)tab，帧标签，高位在前，每个字节的bit[0-6]表示具体值，bit[7]表示下一字节是否属于tab
 * @parame ：(uint8_t)length，数据data长度
 * @parame ：(uint32_t)check，校验位
 */
typedef struct {
    IM_NewMessageFormat format;
    uint8_t key;
    uint32_t tab;
    uint8_t length;
    uint32_t check;
}__attribute__((packed)) IM_NewMessageBody;


@interface IMTCANMessage : NSObject

@property (nonatomic, readonly, assign) IMTCANMessageBody body;
@property (nonatomic, readonly, strong) NSData *extra;
@property (nonatomic, readonly, strong) NSString *key;

// 新协议
@property (nonatomic, assign) IM_NewMessageBody newBody;
@property (nonatomic, assign) IM_NewStandardDataFormat StandardData;
@property (nonatomic, assign) IM_NewDedicatedDataFormat DedicatedData;
@property (nonatomic, strong) NSData *para;;


- (instancetype)initWithBody:(IMTCANMessageBody)body extra:(NSData *)extra;
// r0 生成消息
- (instancetype)initWithCmd:(unsigned char)cmdID otherID:(unsigned char)otherID dev:(unsigned char)dev extra:(NSData *)extra;

// 新协议
// 标准组
- (instancetype)initWithBody:(IM_NewMessageBody)body StandardData:(IM_NewStandardDataFormat)StandardData data:(NSData *)data;
// 专用组
- (instancetype)initWithBody:(IM_NewMessageBody)body DedicatedData:(IM_NewDedicatedDataFormat)DedicatedData data:(NSData *)data;
// 自由组
- (instancetype)initWithBody:(IM_NewMessageBody)body data:(NSData *)data;

@end

